package top.whysu.gps.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.poi.excel.ExcelReader;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import top.whysu.gps.annotation.ExcelColumn;
import top.whysu.gps.constant.CodeConstant;
import top.whysu.gps.constant.GlobalVar;
import top.whysu.gps.dto.navigation.RouteImportExcelDTO;
import top.whysu.gps.exception.BusinessException;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Excel工具类
 */
public class ExcelUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtil.class);
    /**
     * 车位信息导入
     *
     * @param file 车位导入
     * @return 导出的车位list
     */
    public static List<RouteImportExcelDTO> importRouteExcel(MultipartFile file) throws Exception {
        // 校验
        if (null == file || file.isEmpty()) {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "文件不存在！");
        }
        // 文件写入临时目录
        String fileName = System.currentTimeMillis() + RandomUtil.randomNumbers(4) + file.getOriginalFilename();
        String absPath = GlobalVar.Common.STOREPATH
                + File.separator + "file"
                + File.separator + "temp"
                + File.separator + fileName;
        FileWriter fileWriter = new FileWriter(absPath);
        fileWriter.writeFromStream(file.getInputStream());
        // 重新读取文件(获取内容
        ExcelReader reader = cn.hutool.poi.excel.ExcelUtil.getReader(absPath);
        List<Map<String, Object>> dataMaps = reader.readAll();
        reader.close();
        // Map转成Bean
        List<RouteImportExcelDTO> sourceDataList = new ArrayList<>();
        dataMaps.forEach(it -> sourceDataList.add(transMapToJavaBean(it, new RouteImportExcelDTO())));
        return sourceDataList;
    }

    /**
     * 根据读取的字段映射转换到对应的实体字段
     *
     * @param dataMap
     * @param sourceData
     * @param <T>
     * @return
     */
    private static <T> T transMapToJavaBean(Map<String, Object> dataMap, T sourceData) {
        Field[] fields = sourceData.getClass().getDeclaredFields();
        dataMap.forEach((key, val) -> {
            for (Field field : fields) {
                ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class);
                if (excelColumn != null) {
                    String title = excelColumn.title();
                    if (key.equals(title)) {
                        try {
                            field.setAccessible(true);
                            if (null != val && StringUtils.isNotBlank(val.toString())) {
                                String type = field.getType().toString();
                                if (type.endsWith("String")) {
                                    field.set(sourceData, val.toString());
                                } else if (type.endsWith("Long")) {
                                    field.set(sourceData, Long.valueOf(val.toString()));
                                } else if (type.endsWith("Integer")) {
                                    field.set(sourceData, Integer.valueOf(val.toString()));
                                } else if (type.endsWith("Double")) {
                                    field.set(sourceData, Double.valueOf(val.toString()));
                                } else if (type.endsWith("Float")) {
                                    field.set(sourceData, Float.valueOf(val.toString()));
                                } else if (type.endsWith("Boolean")) {
                                    field.set(sourceData, Boolean.valueOf(val.toString()));
                                } else if (type.endsWith("Date")) {
                                    field.set(sourceData, DateUtil.parse(val.toString()));
                                }
                            } else {
                                field.set(sourceData, null);
                            }
                        } catch (IllegalAccessException e) {
                            LOGGER.error("Excel转换异常！", e);
                        }
                    }
                }
            }
        });
        return sourceData;
    }

}
